/*******************************************************************************
 *  Form class
 *  desc: Wrapper for FormElement
 *******************************************************************************

// options example
var options = {
    id: 'id',
    title: 'title',
    showTitle: true,
    description: 'description',
    target: 'targetElement',
    validate: {}
}
*/

var Form = function(options){
    
    // this class should extend an Element class
    $.extend(true, this, new Container(options))
    
    // ------------------------------------------------------- fields
    
    this.validator = null;
    this.buttonsHolder = null;
    this.formElement = new FormElement(options).addClass('sidebar wrapped-form');
    this.steps = new Array();
    
    // ------------------------------------------------------- settings
    
    // prepares settings
    this.defaults = {
        target: $('div.page-content-container'),
        validate: {
            errorElement: "span",
            meta: 'validate'
        }
    };
    
    var settings = this.prepareSettings(options);
    settings.id = settings.id+'-form';
    
    // ------------------------------------------------------- methods
    
    /**
     *  Initiates validation of form controls
     *  @return class instance
     */
    this.initValidation = function(){
        for(var i=0;i<this.steps.length;i++){
            this._bindValidationHandler(this.steps[i]);
        }
        return this;
    }
    
    /**
     *  Adds a step to form
     *  @param step defines form step
     *  @return class instance
     */
    this.addStep = function(step){
        if(step && step instanceof Step) {
            this.formElement.append(step);
            this.steps.push(step);
            this._bindValidationHandler(step)
        }
        return this;
    };
    
    this._bindValidationHandler = function(step){
        var form = this;
        var fields = step.getFields();
        for(var i=0;i<fields.length;i++){
            var field = fields[i];

            var handler = function(e){
                if(e.keyCode==37 || e.keyCode==38 || e.keyCode==39 || e.keyCode==40) return;
                var element = $(this);
                if(element.is(':visible') && this.wrapper.settings.rules){
                    if(!form.validator.element(element)) {
                        this.wrapper.parent.makeInvalid();
                    } else {
                        this.wrapper.parent.makeValid();
                    }
                }
            };
            field.getElement().unbind(); // unbinds all previous handlers
            
            if(field instanceof InputElement || field instanceof TextareaElement){
                if(field.settings.rules && field.settings.rules.isUserUnique){
                    field.getElement()
                        .bind('keyup', handler)
                        .bind('blur', handler)
                } else {
                    field.getElement()
                        .bind('keyup', handler)
                        .bind('keydown', handler)
                        .bind('paste', handler)
                        .bind('change', handler);
                }
            } else {
                field.getElement().bind('change', handler);
            }
        }
    }
    
    /**
     *  Returns first step
     *  @return first step
     */
    this.getFirstStep = function(){
        return this.steps[0];
    };
    
    /**
     *  Adds action button to step
     *  @param button defines button
     *  @return class instance
     */
    this.addButton = function(button){
        if(button){
            this._getButtonsHolder().append(button);
            var form = this;
            if(button.isPrimary()){
                button.getElement()[0].onclick = function(e){
                    if(!form.isValid()) return;
                    if(button.settings.onclick) button.settings.onclick(e);
                };
            }
        }
        return this;
    }

    this._getButtonsHolder = function(){
        if(this.buttonsHolder==null) {
            this.buttonsHolder = new Element($('<div>')).addClass('form-actions');
            this.formElement.append(this.buttonsHolder);
        }
        return this.buttonsHolder;
    }
    
    this.getFields = function(){
        var result = new Array();
        for(var i=0;i<this.steps.length;i++){
            result = result.concat(this.steps[i].getFields());
        }
        return result;
    }
    
    this._getStepIndex = function(step){
        return $.inArray(step, this.steps);
    }
    
    this.getStepByIndex = function(index){
        if(index >= 0 && index < this.steps.length){
            return this.steps[index];
        }
        //console.warn('Step with index = '+index+' is not found');
        return null;
    }
    
    this.isValid = function(){
        var fields = this.getFields();
        for(var i=0;i<fields.length;i++){
            var field = fields[i];
            var element = field.getElement();
            if(element.is(':visible') && field.settings.rules){
                if(!this.validator.element(element)) {
                    field.parent.makeInvalid();
                } else {
                    field.parent.makeValid();
                }
            }
        }
        
        
        return this.validator.form();
    }
    
    // ------------------------------------------------------- preparing
    this.setId(settings.id)
        .append(this.formElement)
        .addClass('span12 sidebar-container');
        
    // enables step validation
    this.validator = this.formElement.getElement().validate(settings.validate);

    // prepares place on page
    var row = $('<div>').addClass('row-fluid').append(this.getElement());
    this.holder = row;
    settings.target.append(row);
    
    console.log('Form was created with id = '+this.getId());
}




/*******************************************************************************
 *  SingleStepForm class
 *******************************************************************************

// options example
var options = {
    id: 'id',
    title: 'title',
    description: 'description',
    target: 'targetElement'
}
*/

var SingleStepForm = function(options){
    
    
    // this class should extend an Form class
    $.extend(true, this, new Form(options))
    
    // ------------------------------------------------------- methods
    
    /**
     *  Adds control to form
     *  @param control defines control
     *  @return class instance
     */
    this.add = function(control){
        this.getFirstStep().add(control);
        return this;
    };
    
    // ------------------------------------------------------- preparing
    options.showTitle = false; // disables step title
    this.addStep(new Step(options));
    
    console.log('SingleStepForm was created with id = '+this.getId());
}